BOJ_14002_가장 긴 증가하는 부분 수열4

LIS(Longest Increasing Subsequence) 알고리즘을 사용해서 가장 긴 증가하는 부분 수열의 원소를 출력하는 문제

BOJ_11053_가장 긴 증가하는 부분 수열
BOJ_12015_가장 긴 증가하는 부분 수열2
BOJ_12738_가장 긴 증가하는 부분 수열3
에서는 길이만 출력했다면, 이번에는 원소를 같이 출력해야 한다

N이 1000이기 때문에 dp만을 사용해서 풀어도 O(N^2) = O(1000^2)이기 때문에 시간적으로 괜찮다


package solve.BJO;  
  
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.util.*;  
  
public class BJO_14002_가장_긴_증가하는_부분_수열4 {  
    public static void main(String[] args) throws IOException {  
        // 4번 문제는 dp로 풀어도 되지만 연습 겸 dp + 이분탐색으로 풀었다  
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
        int N = Integer.parseInt(br.readLine());  
  
        StringTokenizer st = new StringTokenizer(br.readLine());  
        int[] nums = new int[N];  
        for (int i = 0; i < N; i++) {  
            nums[i] = Integer.parseInt(st.nextToken());  
        }  
  
        // dp 배열과 이분탐색을 함께 사용해서  
        // 수열의 정확한 원소를 구하는 문제  
        // 시간복잡도 : NlogN        int[] dp = new int[N];  
        int[] lis = new int[N];  
  
        int length = 0;  
        for (int i = 0; i < N; i++) {  
            int num = nums[i];  
            int pos = binarySearch(lis, 0, length, num);  
            lis[pos] = num;  
            dp[i] = pos;  
  
            if (pos == length) length++;  
        }  
  
        System.out.println(length);  
  
        Integer[] res = new Integer[length];  
        length--;  
        for (int i = N - 1; i >= 0; i--) {  
            if (dp[i] == length) {  
                res[length] = nums[i];  
                length--;  
            }  
        }  
  
        for (Integer num : res) {  
            System.out.print(num + " ");  
        }  
    }  
  
    public static int binarySearch(int[] lis, int start, int end, int target) {  
        while (start < end) {  
            int mid = start + (end - start) / 2;  
  
            if (lis[mid] < target) start = mid + 1;  
            else end = mid;  
        }  
  
        return start;  
    }  
}